package com.leiqichao.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.leiqichao.backend.entity.StatVisit;
import com.leiqichao.backend.mapper.StatVisitMapper;
import com.leiqichao.backend.service.StatVisitService;
import com.leiqichao.backend.util.IpLocationService;
import com.leiqichao.backend.util.UserAgentParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class StatVisitServiceImpl extends ServiceImpl<StatVisitMapper, StatVisit>
    implements StatVisitService {

    // 使用Redis替代ConcurrentHashMap（示例配置）
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    StatVisitMapper statVisitMapper;

    @Autowired
    IpLocationService ipLocationService;

    @Autowired
    UserAgentParser userAgentParser;


    @Override // 如果接口声明了此方法，需要实现
    public IPage<StatVisit> page(Page<StatVisit> pageParam, QueryWrapper<StatVisit> query) {
        // 直接调用父类实现
        return super.page(pageParam, query);
    }



    // Lua 脚本（原子性添加 IP + 设置过期时间）
    private static final String RECORD_IP_SCRIPT =
            "local key = KEYS[1]\n" +
                    "local ip = ARGV[1]\n" +
                    "local expireSeconds = ARGV[2]\n" +
                    "local added = redis.call('SADD', key, ip)\n" +
                    "if added == 1 then\n" +
                    "   if redis.call('TTL', key) == -1 then\n" +
                    "       redis.call('EXPIRE', key, expireSeconds)\n" +
                    "   end\n" +
                    "   return 1\n" +
                    "else\n" +
                    "   return 0\n" +
                    "end";

    @Async
    @Override
    public void recordVisit(String ip, String requestPath, String referrer, String userAgent) throws JsonProcessingException {
        // 1. 生成当天 Key（格式如 20231001）
        String dateKey = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);

        // 2. 执行原子操作：添加 IP 并管理过期时间
        Long result = redisTemplate.execute(
                new DefaultRedisScript<>(RECORD_IP_SCRIPT, Long.class),
                Collections.singletonList(dateKey),
                ip,
                String.valueOf(TimeUnit.DAYS.toSeconds(1)) // 转为秒
        );

        // 3. 可根据需要记录详细访问日志（异步）
        StatVisit statVisit = new StatVisit();
        statVisit.setRequestPath(requestPath);
        statVisit.setUserAgent(userAgentParser.parseToJson(userAgent));
        statVisit.setReferrer(referrer);
        statVisit.setIp(ip);
        log.info("访问ip：{}", ip);
        String ipLocation = ipLocationService.getFormattedIpLocation(ip);
        statVisit.setIpLocation(ipLocation);
        statVisitMapper.insert(statVisit);
    }

    // 统计当日访问量
    public Long getDailyAccessCount() {
        String dateKey = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        return redisTemplate.opsForSet().size(dateKey);
    }
}